<?php
declare(strict_types=1);

namespace app\shop\logic;

use app\shop\enums\coupon\CouponExpiryType;
use app\shop\exception\ParamsErrorException;
use app\shop\library\datetime\TimeHelper;
use app\shop\model\coupon\CouponCenterModel;
use app\shop\model\coupon\CouponModel;
use app\shop\model\user\UserCouponModel;
use Exception;
use think\Paginator;

/**
 * @property CouponCenterModel $couponCenterModel
 */
class CouponLogic extends BaseLogic
{
    public function __construct()
    {
        $this->couponCenterModel = new CouponCenterModel();
    }

    /**
     * 领券中心列表
     * @return Paginator|array
     */
    public function center(): Paginator|array
    {
        $query = CouponCenterModel::getQuery();

        $query->with([
            // 信息通过bind绑定在优惠券上了
            'coupon'      => function ($query) { },
            'user_coupon' => function ($query) {
                $query->withOutField(['create_time', 'update_time']);
            },
        ]);

        $query->hasWhere('coupon', function ($query) {
            $query->where('status', 1);
        })->whereBetweenTimeField('active_start_time', 'active_end_time');

        $query->order(['weigh' => 'desc', 'id' => 'desc']);

        $query->append(['disabled', 'received', 'ran_out', 'ended']);

        $query->hidden(['total_num', 'remain_num', 'limit_num', 'active_start_time', 'active_end_time']);

        return CouponModel::paginateListQuery($query);
    }

    /**
     * 优惠券领券
     * @param array $params
     * @return array
     * @throws ParamsErrorException
     */
    public function receive(array $params): array
    {
        $coupon = CouponCenterModel::where([
            ['id', '=', $params['id']],
        ])->with(['coupon', 'user_coupon'])->lock(true)->findOrEmpty();

        if ($coupon->isEmpty()) {
            throw new ParamsErrorException('优惠券擦肩而过');
        }
        if (time() < $coupon->active_start_time) {
            throw new ParamsErrorException('不要着急噢，领券活动还没开始');
        }
        if (time() > $coupon->active_end_time) {
            throw new ParamsErrorException('来晚了，领券活动已结束');
        }
        if ($coupon->coupon->status != 1) {
            throw new ParamsErrorException('优惠券已失效,请刷新页面');
        }
        if (count($coupon->user_coupon) >= $coupon['limit_num']) {
            throw new ParamsErrorException('很抱歉，领取次数超过限制');
        }
        if ($coupon->remain_num <= 0) {
            throw new ParamsErrorException('来晚了，优惠券已被领完');
        }

        $startTime  = match (intval($coupon['expiry_type'])) {
            CouponExpiryType::FIXED_TIME => $coupon['start_time'],
            default => time(),
        };
        $endTime    = match (intval($coupon['expiry_type'])) {
            CouponExpiryType::FIXED_DAYS => TimeHelper::afterDay($coupon->expiry_days, null, true) - 1,
            default => $coupon->end_time,
        };
        $couponData = [
            'coupon_id'        => $coupon->coupon_id,
            'coupon_center_id' => $coupon->id,
            'user_id'          => $params['user_id'],
            'start_time'       => $startTime,
            'end_time'         => $endTime,
            'status'           => 1,
        ];
        $this->couponCenterModel->startTrans();
        try {
            $this->couponCenterModel->where('id', $coupon['id'])->dec('remain_num')->save();
            $userCoupon = UserCouponModel::create($couponData);

            $this->couponCenterModel->commit();
        } catch (Exception $e) {
            $this->couponCenterModel->rollback();
            throw new ParamsErrorException('活动火爆,请稍后再试', null, $e);
        }

        return [
            'id' => $userCoupon->id,
        ];
    }
}